package xyz.lwm.lazycat.web.handle;

import lombok.Getter;
import xyz.lwm.lazycat.utility.StringUtil;

import java.nio.charset.Charset;

/**
 * 常用 Content-Type 类型枚举
 */
@Getter
public enum ContentType {

	/**
	 * 标准表单编码，当 action为 get时候，浏览器用x-www-form-urlencoded的编码方式把form数据转换成一个字串（name1=value1&amp;name2=value2…）
	 */
	FORM_URLENCODED("application/x-www-form-urlencoded"),
	/**
	 * 文件上传编码，浏览器会把整个表单以控件为单位分割，并为每个部分加上Content-Disposition，并加上分割符(boundary)
	 */
	MULTIPART("multipart/form-data"),
	/**
	 * Rest请求JSON编码
	 */
	JSON("application/json"),
	/**
	 * Rest请求XML编码
	 */
	XML("application/xml"),
	/**
	 * text/plain编码
	 */
	TEXT_PLAIN("text/plain"),
	/**
	 * Rest请求text/xml编码
	 */
	TEXT_XML("text/xml"),
	/**
	 * text/html编码
	 */
	TEXT_HTML("text/html"),
	/**
	 * application/octet-stream编码
	 */
	OCTET_STREAM("application/octet-stream");

    /**
     * -- GETTER --
     *  获取value值
     */
    private final String value;

	/**
	 * 构造
	 *
	 * @param value ContentType值
	 */
	ContentType(String value) {
		this.value = value;
	}

    @Override
	public String toString() {
		return getValue();
	}

	/**
	 * 输出 Content-Type字 符串，附带编码信息
	 *
	 * @param charset 编码
	 * @return Content-Type字符串
	 */
	public String toString(Charset charset) {
		return build(this.value, charset);
	}

	/**
	 * 是否为默认Content-Type，默认包括{@code null}和application/x-www-form-urlencoded
	 *
	 * @param contentType 内容类型
	 * @return 是否为默认Content-Type
	 */
	public static boolean isDefault(String contentType) {
		return null == contentType || isFormUrlEncode(contentType);
	}

	/**
	 * 是否为 multipart/form-data
	 *
	 * @param contentType 内容类习惯
	 */
	public static boolean isMultipart(String contentType) {
		return contentType.toLowerCase().startsWith(MULTIPART.toString());
	}

	/**
	 * 是否为 application/x-www-form-urlencoded
	 *
	 * @param contentType 内容类型
	 * @return true if application/x-www-form-urlencoded
	 */
	public static boolean isFormUrlEncode(String contentType) {
		return contentType.toLowerCase().startsWith(FORM_URLENCODED.toString());
	}

	/**
	 * 是否为 application/json
	 *
	 * @param contentType 内容类型
	 * @return true if application/json
	 */
	public static boolean isApplicationJson(String contentType) {
		return contentType.toLowerCase().startsWith(JSON.toString());
	}

	/**
	 * 是否为 text/plain
	 *
	 * @param contentType 内容类型
	 * @return true if text/plain
	 */
	public static boolean isTextPlain(String contentType) {
		return contentType.toLowerCase().startsWith(TEXT_PLAIN.toString());
	}

	/**
	 * 从请求参数的body中判断请求的Content-Type类型，支持的类型有：
	 *
	 * <pre>
	 * 1. application/json
	 * 1. application/xml
	 * </pre>
	 *
	 * @param body 请求参数体
	 * @return Content-Type类型，如果无法判断返回null
	 */
	public static ContentType get(String body) {
		ContentType contentType = null;
		if (StringUtil.isNotBlank(body)) {
			char firstChar = body.charAt(0);
			switch (firstChar) {
				case '{':
				case '[':
					// JSON请求体
					contentType = JSON;
					break;
				case '<':
					// XML请求体
					contentType = XML;
					break;

				default:
					break;
			}
		}
		return contentType;
	}

	/**
	 * 输出Content-Type字符串，附带编码信息
	 *
	 * @param contentType Content-Type类型
	 * @param charset     编码
	 * @return Content-Type字符串
	 */
	public static String build(String contentType, Charset charset) {
		return StringUtil.format("{};charset={}", contentType, charset.name());
	}

	/**
	 * 输出Content-Type字符串，附带编码信息
	 *
	 * @param contentType Content-Type 枚举类型
	 * @param charset     编码
	 * @return Content-Type字符串
	 */
	public static String build(ContentType contentType, Charset charset) {
		return build(contentType.getValue(), charset);
	}

}
